﻿/*
    a11_TicTacToe @ https://gitee.com/zcatt/MyDemo2020
 演示了eventHandler和基本controls的创建.
 
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

namespace a11_TicTacToe
{
    public partial class Form1 : Form
    {
        enum PieceState {
            State_Null = 0,
            State_X = -1,
            State_O = 1
        };

        private bool m_isOver;
        private bool m_isX;
        private PieceState[] m_states;

        private Panel m_boardPanel;
        private Button m_playBtn;

        public Form1()
        {
            Create();
            NewGame();
        }

        private void Create()
        {
            m_states = new PieceState[9];

            SuspendLayout();

            m_playBtn = new Button();
            m_playBtn.Location = new Point(206, 328);
            m_playBtn.Name = "playBtn";
            m_playBtn.Text = "New &Game";
            m_playBtn.Size = new Size(75, 23);
            m_playBtn.TabIndex = 0;
            m_playBtn.UseVisualStyleBackColor = true;
            m_playBtn.Click += new EventHandler(playBtn_Click);

            m_boardPanel = new Panel();
            m_boardPanel.Location = new Point(10, 12);
            m_boardPanel.Name = "board";
            m_boardPanel.Size = new Size(301, 301);
            m_boardPanel.TabIndex = 1;
            m_boardPanel.MouseClick += new MouseEventHandler(boardPanel_MouseClick);
            m_boardPanel.Paint += new PaintEventHandler(boardPanel_Paint);




            AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            ClientSize = new System.Drawing.Size(320, 363);
            Controls.Add(m_playBtn);
            Controls.Add(m_boardPanel);
            FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
            MaximizeBox = false;
            Name = "Form1";
            Text = "a11_TicTacToe";

            ResumeLayout(false);
        }

        private void NewGame()
        {
            for (int i = 0; i < 9; i++)
                m_states[i] = PieceState.State_Null;
            m_isOver = false;
            m_isX = true;

            //m_states[0] = PieceState.State_X;
        }

        private bool IsGameOver()
        {
            bool res = false;

            int sum;
            for (int i = 0; i < 3; i++)
            {
                sum = (int)m_states[i * 3 + 0] + (int)m_states[i * 3 + 1] + (int)m_states[i * 3 + 2];
                if (sum == 3 || sum == -3)
                {
                    res = true;
                    break;
                }
                sum = (int)m_states[i] + (int)m_states[i + 3] + (int)m_states[i + 6];
                if (sum == 3 || sum == -3)
                {
                    res = true;
                    break;
                }
            }

            if (!res)
            {
                sum = (int)m_states[0] + (int)m_states[4] + (int)m_states[8];
                if (sum == 3 || sum == -3)
                {
                    res = true;
                }
                else
                {
                    sum = (int)m_states[2] + (int)m_states[4] + (int)m_states[6];
                    if (sum == 3 || sum == -3)
                    {
                        res = true;
                    }
                }
            }

            return res;
        }

        public void boardPanel_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Pen pen = new Pen(Color.Blue);

            g.DrawLine(pen, 0, 100, 300, 100);
            g.DrawLine(pen, 0, 200, 300, 200);
            g.DrawLine(pen, 100, 0, 100, 300);
            g.DrawLine(pen, 200, 0, 200, 300);
            g.DrawRectangle(pen, 0, 0, 300, 300);

            Font font = new Font("Microsoft Sans Serif"
                                , 72F
                                , FontStyle.Bold
                                , GraphicsUnit.Point
                                , ((System.Byte)(0)));
            StringFormat sa = new StringFormat();
            sa.Alignment = StringAlignment.Center;
            sa.LineAlignment = StringAlignment.Center;

            for(int i = 0; i< 3; i++)
                for (int j = 0; j < 3; j++)
                {
                    if (m_states[i * 3 + j] == PieceState.State_Null)
                        continue;
                    string ch = (m_states[i * 3 + j] == PieceState.State_X) ? "X" : "O";
                    g.DrawString(ch, font, Brushes.Black, j * 100 + 50f, i * 100 + 50f, sa); 
                }
            pen.Dispose();
        }

        private void playBtn_Click(object sender, EventArgs e)
        {
            NewGame();

            Invalidate(true);
            Update();
        }

        private void boardPanel_MouseClick(object sender, MouseEventArgs e)
        {
            if (m_isOver)
            {
                MessageBox.Show("Already game over! Press 'New Play' to start.", "Warning", MessageBoxButtons.OK);
                return;
            }

            int index = e.X / 100 + e.Y / 100 * 3;
            Debug.WriteLine("index= " + index);
            Debug.Assert(index < 9);

            if (m_states[index] != PieceState.State_Null)
            {
                MessageBox.Show("This pos is already occupied!", "Warning", MessageBoxButtons.OK);
                return;
            }

            m_states[index] = m_isX ? PieceState.State_X : PieceState.State_O;
            m_isX = !m_isX;

            Invalidate(true);
            Update();

            if (IsGameOver())
            {
                m_isOver = true;
                MessageBox.Show("Game Over!", "Info", MessageBoxButtons.OK);
            }
                
        }
    }
}
